#ifndef xpack_test_net_http
#define xpack_test_net_http
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::test_net_http::inc
#include"test/helper.hpp" // 需要放第一
#include"chrono/+.hpp"
#include"lang/cxx.hpp"
#include"net/http.hpp"
#include"utils/memory.hpp"
#include"utils/temp_allocator.hpp"
#include"meta/remove_ref.hpp"
#pragma pop_macro("xuser")

namespace mixc::test_net_http{
    xtest("cookie") {
        auto temp = inc::temp_allocator{};
        auto alloc = temp.item_as<char>();

        // 设置 name
        auto cookie = inc::http::cookie{}->name("token");
        auto prefix_length = sizeof("Set-Cookie:");
        auto actually = cookie.make(alloc);
        auto recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        auto check = [&](inc::http::cookie const & recover, inc::http::cookie const & cookie){
            xassert_eq(recover->name        , cookie->name);
            xassert_eq(recover->value       , cookie->value);
            xassert_eq(recover->path        , cookie->path);
            xassert_eq(recover->domain      , cookie->domain);
            xassert_eq(recover->max_age     , cookie->max_age);
            xassert_eq(recover->is_http_only, cookie->is_http_only);

            return
                recover->name           == cookie->name and
                recover->value          == cookie->value and
                recover->path           == cookie->path and
                recover->domain         == cookie->domain and
                recover->max_age        == cookie->max_age and
                recover->is_http_only   == cookie->is_http_only;
        };

        xassert_eq(actually, "Set-Cookie: token=; path=/; HttpOnly\r\n");
        xassert(check(recover, cookie));


        // 设置 value
        cookie->value = "arg0=1&arg1=2";
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/; HttpOnly\r\n");
        xassert(check(recover, cookie));




        // 设置 path
        cookie->path = "/interface";
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/interface; HttpOnly\r\n");
        xassert(check(recover, cookie));




        // 设置 domain
        cookie->domain = ".cat.com.cn";
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/interface; domain=.cat.com.cn; HttpOnly\r\n");
        xassert(check(recover, cookie));




        // 设置 expires date
        cookie->expires = inc::datetime{2022,6,6};
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/interface; domain=.cat.com.cn; expires=Mon, 06 Jun 2022 00:00:00 GMT; HttpOnly\r\n");
        xassert(check(recover, cookie));



        // 设置 expires max-age
        cookie->max_age = 1200;
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/interface; domain=.cat.com.cn; max-age=1200; HttpOnly\r\n");
        xassert(check(recover, cookie));




        // 使用内存分配，字符串将拥有不同的地址
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), alloc);
        xassert(check(recover, cookie));
        xassert_ne(& recover->name[0], & cookie->name[0]);
        xassert_ne(& recover->value[0], & cookie->value[0]);
        xassert_ne(& recover->path[0], & cookie->path[0]);
        xassert_ne(& recover->domain[0], & cookie->domain[0]);

        // 设置 is_http_only
        cookie->expires = inc::datetime{2022,6,6};
        cookie->is_http_only = false;
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: token=arg0=1&arg1=2; path=/interface; domain=.cat.com.cn; expires=Mon, 06 Jun 2022 00:00:00 GMT\r\n");
        xassert(check(recover, cookie));




        // 只保留 value，不设置 name 和 httponly
        cookie = inc::http::cookie{}->value("valueOnly")->is_http_only(false);
        actually = cookie.make(alloc);
        recover = inc::http::cookie{}.from(actually.backward(prefix_length), inc::http::reuse_cxx_memory);

        xassert_eq(actually, "Set-Cookie: valueOnly; path=/\r\n");
        xassert(check(recover, cookie));




        // 不按顺序初始化
        cookie.from("cookie: key=val; expires=Mon, 06 Jun 2022 00:00:00 GMT; path=/foo/bar; domain=.cat.com.cn;", inc::http::reuse_cxx_memory);

        xassert_eq(cookie->name, "key");
        xassert_eq(cookie->value, "val");
        xassert_eq(cookie->path, "/foo/bar");
        xassert_eq(cookie->domain, ".cat.com.cn");
        xassert_eq(cookie->expires, inc::datetime<>(2022,6,6));
        xassert_eq(cookie->is_http_only, false);
    };

    xtest("header"){
        auto used_bytes = inc::memory::used_bytes();

        {
            auto head = inc::http::header_filter{};
            head->care_list = {
                "B",
                "AC",
                "AB",
                "A",
                "Bb",
                "BBa",
            };

            xassert_eq(head->care_list[0], "A");
            xassert_eq(head->care_list[1], "AB");
            xassert_eq(head->care_list[2], "AC");
            xassert_eq(head->care_list[3], "B");
            xassert_eq(head->care_list[4], "Bb");
            xassert_eq(head->care_list[5], "BBa");
            xassert_eq(head->care_list->length, 6u);

            xassert_eq(head.is_expect("A"), true);
            xassert_eq(head.is_expect("AB"), true);
            xassert_eq(head.is_expect("AC"), true);
            xassert_eq(head.is_expect("B"), true);
            xassert_eq(head.is_expect("Bb"), true);
            xassert_eq(head.is_expect("BBa"), true);

            xassert_eq(head.is_expect("a"), true);
            xassert_eq(head.is_expect("aB"), true);
            xassert_eq(head.is_expect("Ab"), true);
            xassert_eq(head.is_expect("BB"), true);
            xassert_eq(head.is_expect("bB"), true);
            xassert_eq(head.is_expect("bBa"), true);
            xassert_eq(head.is_expect("bBA"), true);
            xassert_eq(head.is_expect("bba"), true);

            xassert_eq(head.is_expect("A0"), false);
            xassert_eq(head.is_expect("Abb"), false);
            xassert_eq(head.is_expect("ACd"), false);
            xassert_eq(head.is_expect("Bbb"), false);
            xassert_eq(head.is_expect("Bbaa"), false);

            head->care_list = {};
            xassert_eq(head->care_list->length, 0u);
        }

        xassert_eq(used_bytes, inc::memory::used_bytes());
    };
}

#endif
